package com.mou.boot.controller;

import com.github.jsonzou.jmockdata.JMockData;
import com.github.jsonzou.jmockdata.MockConfig;
import com.mou.boot.entity.User;
import com.mou.boot.exception.ResourceNotFoundException;
import com.mou.boot.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.Objects;

/**
 * Created by mou on 2018/5/8.
 * https://www.ibm.com/developerworks/cn/java/spring5-webflux-reactive/index.html
 * @author Mou
 * @date 2018/5/8
 * @since 1.0
 */
@RestController
@RequestMapping("/user")
public class UserController {

    private final String LOG_STRING = "*****************************************执行的方法：{} ";
    private final Logger LOG = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;

    @ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "Resource not found")
    @ExceptionHandler(ResourceNotFoundException.class)
    public void notFound() {
    }

    /**
     * 初始化测试数据
     * @return
     */
    @PostMapping("/init")
    public Flux<User> init() {
        LOG.info(LOG_STRING, "init");
        final String LAST_NAME_STR = "赵,钱,孙,李,周,吴,郑,王,冯,陈,褚,卫,蒋,沈,韩,杨,朱,秦,尤,许,何,吕,施,张,孔,曹,严,华,金,魏,陶,姜,戚,谢,邹,喻,柏,水,窦,章,云,苏,潘,葛,奚,范,彭,郎,鲁,韦,昌,马,苗,凤,花,方,俞,任,袁,柳,酆,鲍,史,唐,费,廉,岑,薛,雷,贺,倪,汤";
        final String FIRST_NAME_STR = "涛,昌,进,林,有,坚,和,彪,博,诚,先,敬,震,振,壮,会,群,豪,心,邦,承,乐,绍,功,松,善,厚,庆,磊,民,友,裕,河,哲,江,超,浩,亮,政,谦,亨,奇,固,之,轮,翰,朗,伯,宏,言,若,鸣,朋,斌,梁,栋,维,启,克,伦,翔,旭,鹏,泽,晨,辰,士,以,建,家,致,树,炎,德,行,时,泰,盛,雄,琛,钧,冠,策,腾,伟,刚,勇,毅,俊,峰,强,军,平,保,东,文,辉,力,明,永,健,世,广,志,义,兴,良,海,山,仁,波,宁,贵,福,生,龙,元,全,国,胜,学,祥,才,发,成,康,星,光,天,达,安,岩,中,茂,武,新,利,清,飞,彬,富,顺,信,子,杰,楠,榕,风,航,弘";
        final MockConfig mockConfig = new MockConfig()
                .intRange(12, 67)
                .longRange(1, 10)
                .dateRange("2010-01-01", "2020-12-30")
                .sizeRange(1, 2)
                .stringSeed(FIRST_NAME_STR.split(","))
                .charSeed((char) 97, (char) 98);

        final MockConfig lastNameMockConfig = new MockConfig()
                .sizeRange(1, 1)
                .stringSeed(LAST_NAME_STR.split(","));

        Flux<User> userFlux = Flux.generate(ArrayList::new, (list, skin) -> {
            User user = JMockData.mock(User.class, mockConfig);
            String lastName = JMockData.mock(String.class, lastNameMockConfig);
            user.setName(lastName + user.getName());
            list.add(user);
            skin.next(user);
            if (list.size() >= 10) {
                skin.complete();
            }
            return list;
        });
        return this.userService.saveOrupdate(userFlux);
    }

    @GetMapping
    public Flux<User> getList() {
        LOG.info(LOG_STRING, "getList");
        return this.userService.getList();
    }

    @GetMapping("/{id}")
    public Mono<User> getById(@PathVariable("id") final Long id) {
        LOG.info(LOG_STRING, "getById");
        return this.userService.getById(id);
    }

    @PostMapping
    public Flux<User> saveUser(@RequestBody final Flux<User> user) {
        LOG.info(LOG_STRING, "saveUser");
        return this.userService.saveOrupdate(user);
    }

    @DeleteMapping("/{id}")
    public Mono<User> delete(@PathVariable("id") final Long id) {
        LOG.info(LOG_STRING, "delete");
        return this.userService.delete(id);
    }

    @PutMapping("/{id}")
    public Mono<User> update(@PathVariable("id") final Long id, @RequestBody final User user) {
        LOG.info(LOG_STRING, "update");
        Objects.requireNonNull(user);
        user.setId(id);
        return this.userService.saveOrupdate(user);
    }
}
